import xID from "./xID.js";
import { replaceByObj,deleteArrayByCode,upload} from "./xUtil.js";
import {findJsonByCode} from "./treeUtil.js";
import xImage from "./xImage.js";
import xSpin from "./xSpin.js";
import xHint from "./xHint.js";
import xGrid from './xGrid.js';
import {getImageMatrix,imageRotate,canvasToBlob,
    imgBase64ToBlob,getThumbnail,addMarkByMatrix} from "./canvasUtil.js";

/*
*
*   item: {
*      img: imgae
*      imgByMark： 增加了水印的 image
*      state : 1|2|3|4  1:图片上传完毕  2：缩略图上传完毕 3：全部上传完毕 4：已有的不需要上传，不能更改
*   }
*
* */

const tmplBase = `
        <div class="{{class}} xhead">
             <div class="body">               
                             
             </div>  
         <input type="file" id ="{{inputID}}" style="display: none;" accept="image/*">     
        </div>`;

const tmplItem =`<div class="item" data-code="{{code}}">
        {{item}}
         <div class="footer">        
               <i class="flat icon-upload-pic" title="选择图片"></i>
               <i class="flat icon-rotate-left" title ="左旋90度"></i>
               <i class="flat icon-rotate-right" title ="右旋90度"></i>
               <i class="flat icon-delete" title ="删除"></i>
               <i class="flat icon-upload" title ="上传"></i>
         </div>
     </div>`;

const tmplImage = `<div class="item-image {{state}}" style="min-width:{{width}}px;min-height:{{height}}px"> </div>`;

const tmplEmpty = `<div class="item-empty" style="min-width:{{width}}px;min-height:{{height}}px">{{placeholder}}</div>`;

export default class xThumbnail {
    /* 定义变量 开始*/
    // jquery 对象
    $root;
    $head;
    $body;
    $input;
    vInputId = xID.getID();
    vBindEvent;
    vClickId = 'click.'+xID.getID();
    vMarkMatrix;
    vItems = [];
    vImageSize ;
    //当前操作的item;
    vActiveItem;
    vTmpEvent ={};
    vValue ='';


    /* 定义变量 结束*/
    constructor(cfg) {
        this.$root = $('#' + cfg.el);
        this.$root.html(replaceByObj(tmplBase,{class:cfg.style||'thumbnail',
            inputID:this.vInputId}));
        this.vCfg = cfg;
        this.init();
    };

    /* 渲染区块 开始 */
    init() {
        this.$head = this.$root.find('.xhead');
        this.$input = this.$root.find('#'+this.vInputId);
        this.$body = this.$root.find(".body");

        this.vImageSize = (this.vCfg.imageSize||'400').split('*');
        if(!this.vImageSize[1])
            this.vImageSize[1] = this.vImageSize[0];

        this.renderBody();
        this.initEvent();
        if(this.vCfg.mark)
            this.loadMarkMatrix();
    };

    initEvent(){
        this.$root.on('click','.icon-upload-pic',this.evOpen.bind(this));
        this.$input.on('change',this.evInputChange.bind(this));
        this.$root.on('click','.icon-rotate-left',this.evRotateLeft.bind(this));
        this.$root.on('click','.icon-rotate-right',this.evRotateRight.bind(this));
        this.$root.on('click','.item-image',this.evView.bind(this));
        this.$root.on('click','.icon-delete',this.evDelete.bind(this));
        this.$root.on('click','.icon-upload',this.evUpload.bind(this));

        this.$root.on('click', this.evRootClick.bind(this));

    }

    renderBody() {
        let items = [...this.vItems];
        if((this.vCfg.size && items.length<this.vCfg.size)|| !this.vCfg.size){
            items.push({
                type:"empty",
                code:-1,
                placeholder:this.vCfg.placeholder
            })
        }
        this.$body.html(xGrid.renderGrid({
            data: items,
            cbRenderCell: this.renderItem.bind(this),
            col: this.vCfg.col||'col-md-6'
        }));

        this.appendImage();
    }

    appendImage(){
        for(let i of this.vItems){
            let imgDiv = this.$body.find('[data-code="'+i.code+'"]>.item-image');
            //如果图片已有,则不考虑 加水印
            let el = i.state==4?i.img:(i.imgByMark||i.img);
            imgDiv.html(el);
        }
    }

    changeState(item){
        let imgDiv = this.$body.find('[data-code="'+item.code+'"]>.item-image');
        let state = item.state==3?'uploaded':'unupload';
        imgDiv.removeClass('uploaded');
        imgDiv.removeClass('unupload');
        imgDiv.addClass(state);
    }

    loadMarkMatrix(){
        let img = new Image();
        let _this = this;
        img.onload = function(){
            let cvs = document.createElement('canvas');
            let ctx = cvs.getContext("2d");
            cvs.width = img.width;
            cvs.height = img.height;
            ctx.drawImage(img,0,0);
            _this.vMarkMatrix =
                getImageMatrix(ctx.getImageData(0,0,cvs.width,cvs.height));
            cvs.remove();
            img.remove();
        };
        img.src = this.vCfg.mark;
    }

    uploadImg(item){
        let cfg ={ uploadUrl:this.vCfg.uploadUrl||''};
        cfg.file = imgBase64ToBlob(item.imgByMark||item.img);
        cfg.readystatechange = this.evReadystatechange.bind(this);
        cfg.error = this.evUploadError.bind(this);
        cfg.timeout = this.evUploadTimeout.bind(this);
        cfg.item = item;
        cfg.type = 'image';
        upload(cfg);
    }

    uploadThumbnail(item){
        let cfg ={ uploadUrl:this.vCfg.uploadUrl||''};
        cfg.file = canvasToBlob(getThumbnail(item.imgByMark||item.img,this.vCfg.thumbnailSize));
        cfg.readystatechange = this.evReadystatechange.bind(this);
        cfg.error = this.evUploadError.bind(this);
        cfg.timeout = this.evUploadTimeout.bind(this);
        cfg.item = item;
        cfg.type = 'thumbnail';
        upload(cfg);
    }

    syncBindData(){
        let tmp = this.vItems.filter(value => value.state ==3 || value.state==4);

        if((this.vCfg.valueType||'code') =='code'){
            let value ='';
            for(let item of tmp){
                if(item.thumbnailUrl)
                    value += item.imgUrl+'||'+item.thumbnailUrl+',';
                else
                    value += item.imgUrl+',';
            }
            this.vValue = value.substring(0,value.length-1);
            this.vBindEvent(this.vValue);
        }

        else
            this.vBindEvent(tmp);
    }


    evReadystatechange(e,cfg){
        let xhr = e.target;
        if(xhr.readyState == XMLHttpRequest.DONE && xhr.status == 500){
            xSpin.close();
            xHint.pop("网络错误,上传失败!",$(cfg.item.imgByMark||cfg.item.img))
        };

        if (xhr.readyState == XMLHttpRequest.DONE && xhr.status == 200) {
            let body = JSON.parse(xhr.responseText);
            let filename = body.filename||body.FileName|| body.file_name||body.fileName;
            let url = body.url||body.URL||(this.vCfg.path+'/'+filename) ;
            cfg.request = null;

            let item =cfg.item;
            switch(cfg.type){
                case 'image':
                    item.state = (item.state||0)+1;
                    //不需要 缩略图
                    if(!this.vCfg.thumbnailSize)
                        item.state =3 ;
                    item.imgUrl = url;
                    break;
                case 'thumbnail':
                    item.thumbnailUrl = url;
                    item.state = (item.state||0)+2;
                    break;
            }

            if(item.state==3){
                xSpin.close();
                xHint.pop("图片上传成功",item.imgByMark||item.img);
                this.changeState(item);

                if(this.vBindEvent)
                    this.syncBindData();

            }
            /*
            this.verify();
            if(this.vBindEvent)
                this.vBindEvent(this.vValue);
            xHint.pop("剪切上传成功","#"+this.vIDs.clipId)*/
        }
    }

    evUploadError(e,cfg){
        xSpin.close();
        xHint.pop("上传失败!",cfg.item.img);
    }

    evUploadTimeout(e,cfg){
        xSpin.close();
        xHint.pop("上传超时!",cfg.item.img);
    }

    renderStatus(action,status){
        if(action=='add'){
            this.$head.addClass(status);
        }else{
            this.$head.removeClass(status);
        }
    }

    initValue(value) {
        let tmp ;
        if(value){
            if(value !=this.vValue){
                if(Array.isArray(value))
                    tmp =[...value];
                else
                    tmp = value.split(',');
                this.vItems =[];
                tmp.forEach(file =>{
                    let filename = file.split('||')[0];
                    let item = {
                        filename:filename,
                        code:xID.getID(),
                        url:file,
                        type:'image',
                        state:4
                    };
                    this.createImgInItem(item);
                    item.img.crossOrigin = 'Anonymous';
                    item.img.src = filename;
                    this.vItems.push(item);
                })
                this.vValue = value;
            }
        }else{
            this.vValue = value;
            this.vItems =[];
            this.renderBody();
            this.verify();
        }
    }

    renderItem(item){
        let html ='';
        switch(item.type){
            case 'image':
                html = this.renderImage(item);
                break;
            case 'empty':
                html = this.renderEmpty();
                break;

        }
        return replaceByObj(tmplItem,{code:item.code,item:html});
    }

    renderImage(item){
        let state = item.state==3?'uploaded':item.state==4?'':'unupload';
        return replaceByObj(tmplImage,{state,width:this.vImageSize[0],height:this.vImageSize[1]});
    }

    renderEmpty(){
        return replaceByObj(tmplEmpty,{width:this.vImageSize[0],
            height:this.vImageSize[1],
            placeholder:this.vCfg.placeholder||'图片预览'});
    }

    evUpload(e){
        let $item = e.target.parentNode.parentNode;
        let code = $item.getAttribute("data-code");
        if(code !='-1'){
            let item = findJsonByCode(this.vItems,code);
            if(item.state !=4){
                xSpin.pop(item.imgByMark||item.img);
                item.state =0 ;
                this.uploadImg(item);
                if(this.vCfg.thumbnailSize)
                    this.uploadThumbnail(item);
            }
        }
    }

    evOpen(e){
        let $item = e.target.parentNode.parentNode;
        let code = $item.getAttribute("data-code");
        if(code !='-1')
            this.vActiveItem = findJsonByCode(this.vItems,code);
        else
            this.vActiveItem = null;

        this.$input[0].click();
    }

    evRootClick(e){
        this.vTmpEvent.timestamp = e.timestamp;
        this.vTmpEvent.target =e .target;
        this.renderStatus("add","active");
        $(document).on(this.vClickId,this.evOff.bind(this));
    };

    evView(e){
        let $item = e.currentTarget.parentNode;
        //console.log($item);
        let code = $item.getAttribute("data-code");
        let item = findJsonByCode(this.vItems,code);
        let el = item.state==4?item.img:(item.imgByMark||item.img);
        xImage.pop($(el));
    }

    evDelete(e){
        let $item = e.target.parentNode.parentNode;
        let code = $item.getAttribute("data-code");
        if(code != "-1"){
            deleteArrayByCode(this.vItems,code);
            this.renderBody();
        }
    }

    evRotateRight(e){
       let $item = e.target.parentNode.parentNode;
       let code = $item.getAttribute("data-code");
       if(code != "-1" ) {
           let item = findJsonByCode(this.vItems, code);
           if(item.state ==4)
               return;
           imageRotate(item.img, 90);
           if(this.vMarkMatrix){
               item.imgByMark.src = addMarkByMatrix(item.img,this.vMarkMatrix,this.vCfg.markPos);
           }
           item.state =0;
       }
    }

    evRotateLeft(e){
        let $item = e.target.parentNode.parentNode;
        let code = $item.getAttribute("data-code");
        if(code != "-1") {
            let item = findJsonByCode(this.vItems, code);
            if(item.state ==4)
                return;
            imageRotate(item.img, -90);
            if(this.vMarkMatrix){
                item.imgByMark.src = addMarkByMatrix(item.img,this.vMarkMatrix,this.vCfg.markPos);
            }
            item.state =0;
        }
    }

    evInputChange(e){
        let _this = this;
        if(this.$input[0].files[0]){
            //xSpin.pop(this.$body[0]);
            let reader =  new FileReader();
            reader.onload = function(e){
                if(_this.vActiveItem){
                    //_this.vActiveItem.img.src = e.target.result;
                    _this.createImgInItem(_this.vActiveItem);
                    _this.vActiveItem.img.src = e.target.result;
                    _this.vActiveItem.state = 0;
                }else{
                    let item = { code: xID.getID(),type:'image',state:0};
                    _this.createImgInItem(item);
                    item.img.src = e.target.result;
                    _this.vItems.push(item);
                }
            }
            reader.readAsDataURL(this.$input[0].files[0]);
        }
    }

    evOff(e) {
        if((e.type=='click' && (this.vTmpEvent.timestamp !=e.timestamp || this.vTmpEvent.target !=e.target))){
            this.renderStatus('remove','active');
            this.verify();
            $(document).unbind(this.vClickId);
        }
    }

    // 增加 mark
    evImageByMarkLoad(e,item){
        this.renderBody();
    }

    evImageLoad(e,item){
        //默认
        //console.log(item);
        if(item.state ==4){
            this.renderBody();
        }else{
            //是否有水印
            if(this.vMarkMatrix){
                item.imgByMark.src = addMarkByMatrix(item.img,this.vMarkMatrix,this.vCfg.markPos);
            }else{
                this.renderBody();
            }
        }

    }

    createImgInItem(item){
        let img = new Image();
        let _this = this;
        item.img = img;
        img.style.maxHeight = this.vImageSize[1]+'px';
        img.style.maxWidth = this.vImageSize[0]+'px';
        img.onload = function(e){
            //addMarkByMatrix(item.img,_this.vMarkMatrix);
            _this.evImageLoad.bind(_this)(e,item);
        }

        if(this.vCfg.mark){
            let imgByMark = new Image();
            imgByMark.style.maxHeight = this.vImageSize[1]+'px';
            imgByMark.style.maxWidth = this.vImageSize[0]+'px';
            item.imgByMark = imgByMark;
            imgByMark.onload = function(e){
                _this.evImageByMarkLoad.bind(_this)(e,item);
            }
        }
    }

    setBindEvent(event) {
        this.vBindEvent = event;
    };

    setValue(value) {
        this.initValue(value);
    };


    verify() {
        let result = true;
        let tmp = this.vItems.filter(value => value.state == 3 || value.state ==4 );
        if(this.vCfg.mandatory ){
            if(tmp.length<1){
                this.renderStatus("remove",'valid');
                this.renderStatus("add","invalid");
                result =false
            }else {
                this.renderStatus("remove",'invalid');
                this.renderStatus("add","valid");
            }
        }
        return result;
    }

    getValue() {
        return this.vItems.filter(value => value.state == 3 || value.state ==4);
    }

}